/****************************************************************
 *  This file created by writerB.php on 03/21/2007 at 18:18:31  *
 ****************************************************************
 *  writerB.php created by Tonk (tonk@ctonk.com) in 2007        *
 ****************************************************************
 *                 General Document Information
 *
 *  File Name: mob.cpp
 *  Class Name: Mob
 *  Parent Classes: Creature 
 *  Data members: 2
 *  Notes:
 ****************************************************************/

#include <iostream>
#include "combined.h"
#include "stringutil.h"
#include "world.h"



int Mob::numMobs = 0;
int Mob::mobIndex = 0;


// Default constructor...
Mob::Mob(): Creature::Creature() {
	setMobID( ++mobIndex );
	setRoom( NULL );
	setVnum( 0 );
	setFlags( 0 );
	setWhenMove( 0 );
	// Increment the object count...
	numMobs++;
}

// Additional constructors...
Mob::Mob( const unsigned& vnum ): Creature::Creature() {
	setMobID( ++mobIndex );
	setRoom( NULL );
	setVnum( vnum );
	setFlags( 0 );
	setWhenMove( 0 );
	// Increment the object count...
	numMobs++;
}

// Copy constructor (Doesn't change _MobID)...
Mob::Mob( const Mob& ref ): Creature::Creature( ref ) {
	setMobID( ++mobIndex );
	setRoom( NULL );
	setVnum( ref.getVnum() );
	setFlags( ref.getFlags() );
	setWhenMove( ref.getWhenMove() );
	// Increment the object count...
	numMobs++;
}

// Destructor...
Mob::~Mob() {
	// Decrement the object count...
	numMobs--;
}

// Assignment operator (Doesn't change _MobID)...
Mob& Mob::operator = ( const Mob& ref ) {
	setVnum( ref.getVnum() );
	setFlags( ref.getFlags() );
	setWhenMove( ref.getWhenMove() );
	return *this;
}

// Protected Methods...
void Mob::setMobID( const int& MobID ) { // protected
	_MobID = MobID;
}

void Mob::move( void ) { // protected
	int dir = 0;
	int i = 0;
	Room* from = getRoom();
	Room* to = NULL;
	std::string buf;

	if ( from->noExits() ) {
		// This room has no exits, so there's no point trying to move...
		reset();
		return;
	}

	while ( 1 ) {
		i++;
		dir = Timestamp::Instance().random( 6 );
		if ( getRoom()->getExit( dir )->getThere() ) {
//&& World::Instance().FindRoom( _room->GetExit( dir ).GetPoint() )->GetArea() == _area->GetNumber() ) {
			if ( ( to = World::Instance().getRoom( getRoom()->getExit( dir )->getPoint() ) ) == NULL )
				continue;
			from->drop( this );
			buf = getShortDesc();
			if ( dir >= NORTH && dir < UP )
				buf << " has left to the " << Exit::direction2string( dir ) << ".";
			else if ( dir == UP )
				buf << " has left up.";
			else
				buf << " has left down.";
			from->send( buf );
			buf = getShortDesc();
			if ( dir >= NORTH && dir < UP )
				buf << " has arrived from the " << Exit::direction2string( Exit::inverse( dir ) );
			else if ( dir == UP )
				buf << " has arrived from below.";
			else
				buf << " has arrived from above.";
			to->send( buf );
			to->add( this );
			setRoom( to );
			reset();
			return;
		}
		if ( i > 10 ) {
			reset();
			return;
		}
	}

	return;
}

void Mob::reset( void ) { // protected
	time_t current;
	time( &current );
	setWhenMove( current + (time_t)Timestamp::Instance().random( LOWER_ACT, UPPER_ACT ) );
	return;
}

// Public accessor methods...
int Mob::getMobID( void ) const { // public
	return _MobID;
}

void Mob::setRoom( Room* room ) {
	_room = room;
	return;
}

void Mob::setVnum( const unsigned& vnum ) { // public
	_vnum = vnum;
	return;
}

unsigned Mob::getVnum( void ) const { // public
	return _vnum;
}

void Mob::setFlags( const unsigned& flags ) { // public
	_flags = flags;
	return;
}

unsigned Mob::getFlags( void ) const { // public
	return _flags;
}

void Mob::setWhenMove( const time_t& whenMove ) { // public
	_whenMove = whenMove;
	return;
}

time_t Mob::getWhenMove( void ) const { // public
	return _whenMove;
}

// General methods...
void Mob::update( void ) { // public
	time_t current;
	time( &current );

	if ( getWhenMove() <= current ) {
		move();
		reset();
	}

	return;
}

// Static methods...

// Associated operators...
std::ostream& operator << ( std::ostream& write, Mob& mob ) { // associated
	write << "\n**MOB\n";
	mob.save( write );	// Saves only Creature data...

	write << "// Mob data...\n";
	write << mob.getVnum() << '\n';

	return write;
}

std::ostream& operator << ( std::ostream& write, Mob* mob ) { // associated
	return ( write << *mob );
}

std::istream& operator >> ( std::istream& read, Mob& mob ) { // associated
	unsigned vnum = 0;
	mob.load( read );	// Loads only Creature data...

	read >> vnum;
	mob.setVnum( vnum );

	return read;
}

std::istream& operator >> ( std::istream& read, Mob* mob ) { // associated
	return ( read >> *mob );
}
